﻿using Redis;
using SuperiorCommon;
using SuperiorModel;
using SuperiorShopBussinessService;
using System;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using WxPayAPIMobileShopCode.Common.Helpers;

namespace Api.WeiXinGroup.Controllers
{
    [ApiExceptionAttribute]
    public class OrderController : ApiControllerBase
    {
        private IGroupOrderService _IGroupOrderService;
        // GET: Order
        public OrderController(IGroupOrderService IGroupOrderService)
        {
            _IGroupOrderService = IGroupOrderService;
        }
        protected override void Dispose(bool disposing)
        {
            this._IGroupOrderService.Dispose();
            base.Dispose(disposing);
        }

        /// <summary>
        /// 读取用户金币记录
        /// </summary>
        /// <param name="criteria"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResultModel<object> GoldList(Api_GroupGoldLogCriteria criteria)
        {
            var _userid = base.ValidataParms(criteria.UserId);
            if (_userid == null)
                return Error("非法参数");
            criteria.UserId = _userid;
            var res = _IGroupOrderService.GoldLogList(criteria);
            return Success(res);
        }

        /// <summary>
        /// 创建订单
        /// </summary>
        /// <param name="criteria"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResultModel<object> CreateOrder_Cart(Api_GroupBuyGoldRequestModel model)
        {
            var _userid = base.ValidataParms(model.UserId);
            if (_userid == null)
                return Error("非法参数");
            model.UserId = _userid;
            //验证金额
            var _tAmount = model.Gold / 10;
            //if (Convert.ToInt32(model.Amount) != _tAmount)
            //    return Error("非法金额");
            string msg = "";
            var res = _IGroupOrderService.CreateGoldOrder(model, out msg);
            res.AppType = 1;
            if (msg != "")
                return Error(msg);
            if (res.OrderID == 0)
                return Error("Orderid异常");
            Api_GroupCreateOrderResultModel resultmodel = new Api_GroupCreateOrderResultModel();
            resultmodel.OrderID = res.OrderID;

            //微信统一下单
            WxPayData wxd = WeiXinCreateOrder(res);
            if (wxd == null)
                return Error("微信统一下单失败");

            var payParamater = new Api_GroupOrderPayResultModel();
            payParamater.AppId = wxd.GetValue("appId").ToString();
            payParamater.TimeStamp = wxd.GetValue("timeStamp").ToString();
            payParamater.NonceStr = wxd.GetValue("nonceStr").ToString();
            payParamater.Package = wxd.GetValue("package").ToString();
            payParamater.SignType = wxd.GetValue("signType").ToString();
            payParamater.PaySign = wxd.GetValue("paySign").ToString();
            payParamater.Payorderno = wxd.GetValue("payorderno").ToString();
            payParamater.Orderno = wxd.GetValue("orderno").ToString();

            resultmodel.PayParamater = payParamater;

            //存储当前订单的拉起微信支付的模型
            RedisManager.Set<Api_GroupCreateOrderResultModel>(payParamater.Orderno + _userid, resultmodel, DateTime.Now.AddMinutes(15));
            return Success(resultmodel);
        }

        private WxPayData WeiXinCreateOrder(Api_GroupWeixinCreateOrderModel model)
        {
            LogManger.Instance.WriteLog("统一下单参数" + model.ToJson());
            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            string notifyurl = ConfigSettings.Instance.WxCallBackUrl;
            string paykey = model.Paykey;
            string time_start = DateTime.Now.ToString("yyyyMMddHHmmss");
            string time_expire = DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss");
            //统一下单
            WxPayData data = new WxPayData();
            data.SetValue("appid", model.Appid);//公众账号ID
            data.SetValue("mch_id", model.Mch_id);//商户号
            data.SetValue("nonce_str", ToolManager.GenerateNonceStr());//随机字符串
            data.SetValue("body", "正在卖的商品");//商品描述
                                            //data.SetValue("attach", "test");//附加数据
            data.SetValue("out_trade_no", model.OrderNumber);//商户订单号
            data.SetValue("total_fee", (int)Math.Round(model.TotalFee * 100));//总金额 单位分
            data.SetValue("time_start", time_start);
            data.SetValue("time_expire", time_expire);
            //data.SetValue("goods_tag", "test");//商品标记 代金券或立减优惠功能的参数
            data.SetValue("trade_type", "JSAPI");
            data.SetValue("openid", model.Openid);
            data.SetValue("notify_url", notifyurl);//异步通知url
            data.SetValue("spbill_create_ip", "");//终端ip
            data.SetValue("sign", data.MakeSign(model.Paykey));
            string xml = data.ToXml();
            string response = WeiXinHelper.Post(xml, url, false, 10);

            LogManger.Instance.WriteLog("微信统一下单" + response);
            WxPayData result = new WxPayData();
            result.FromXml(response);
            //签名验证
            // 错误时没有签名
            if (result.IsSet("return_code") && result.GetValue("return_code").ToString() == "SUCCESS" && result.IsSet("sign") && result.GetValue("sign").ToString() != "")
            {
                //获取接收到的签名
                string return_sign = result.GetValue("sign").ToString();
                //在本地计算新的签名
                string cal_sign = result.MakeSign(paykey);
                if (cal_sign == return_sign)
                {
                    if (result.IsSet("appid") && result.IsSet("prepay_id") && result.GetValue("prepay_id").ToString() != "")
                    {
                        string prepay_id = result.GetValue("prepay_id").ToString();
                        WxPayData jsApiParam = new WxPayData();
                        jsApiParam.SetValue("appId", result.GetValue("appid"));
                        jsApiParam.SetValue("timeStamp", ToolManager.ConvertDateTimeInt(DateTime.Now));
                        jsApiParam.SetValue("nonceStr", ToolManager.GenerateNonceStr());
                        jsApiParam.SetValue("package", "prepay_id=" + prepay_id);
                        jsApiParam.SetValue("signType", "MD5");
                        jsApiParam.SetValue("paySign", jsApiParam.MakeSign(paykey));
                        //
                        //jsApiParam.SetValue("payorderno", prepay_id);
                        jsApiParam.SetValue("payorderno", model.OrderNumber);
                        jsApiParam.SetValue("orderno", model.OrderNumber);
                        return jsApiParam;
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {

                    LogManger.Instance.WriteLog("订单号：" + model.OrderNumber + ";接收到签名：" + return_sign + ";本地签名：" + cal_sign);
                    return null;
                }
            }
            else
            {
                if (result.IsSet("return_msg") && result.GetValue("return_msg").ToString() != "")
                {
                    LogManger.Instance.WriteLog("订单号：" + model.OrderNumber + ";微信支付预处理失败：" + result.GetValue("return_msg").ToString());
                    return null;
                }
                else
                {
                    return null;
                }
            }
        }
        private static object LockData = new object();

        /// <summary>
        /// 微信支付回调
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public HttpResponseMessage WxCallBack()
        {
            //接收从微信后台POST过来的数据
            System.IO.Stream s = System.Web.HttpContext.Current.Request.InputStream;
            int count = 0;
            byte[] buffer = new byte[1024];
            StringBuilder builder = new StringBuilder();
            while ((count = s.Read(buffer, 0, 1024)) > 0)
            {
                builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
            }
            s.Flush();
            s.Close();
            s.Dispose();
            LogManger.Instance.WriteLog("微信回调返回数据：" + builder.ToString());
            //转换数据格式并验证签名
            WxPayData data = new WxPayData();
            try
            {
                data.FromXml(builder.ToString());
                //2015-06-29 错误时没有签名
                if (data.IsSet("return_code") && data.GetValue("return_code").ToString() == "SUCCESS" && data.IsSet("sign") && data.GetValue("sign").ToString() != "")
                {
                    string appid = data.GetValue("appid").ToString();
                    string paykey = ConfigSettings.Instance.PaySecret;
                    if (appid != null)
                    {
                        //获取接收到的签名
                        string return_sign = data.GetValue("sign").ToString();
                        //在本地计算新的签名
                        string cal_sign = data.MakeSign(paykey);
                        if (cal_sign == return_sign)
                        {
                            //更新订单状态
                            string out_trade_no = data.GetValue("out_trade_no").ToString();
                            //重复调用验证
                            lock (LockData)
                            {

                                if (RedisManager.Get<string>(out_trade_no) != null)
                                {
                                    LogManger.Instance.WriteLog("微信支付回调发生了频繁重复调用！订单号" + out_trade_no);
                                    return null;
                                }
                                else
                                {
                                    //将当前订单号写入缓存
                                    RedisManager.Set(out_trade_no, out_trade_no, DateTime.Now.AddMinutes(15));
                                }
                            }
                            string transaction_id = data.GetValue("transaction_id").ToString();
                            string result_code = data.GetValue("result_code").ToString();
                            string err_code = data.IsSet("err_code") ? data.GetValue("err_code").ToString() : string.Empty;
                            string time_end = data.GetValue("time_end").ToString();
                            float total_fee = 0; Int64 paytime; int status = 0;
                            float.TryParse(data.GetValue("total_fee").ToString(), out total_fee);
                            Int64.TryParse(time_end, out paytime);
                            if (result_code == "SUCCESS")
                            {
                                status = 1;
                            }
                            else if (result_code == "FAIL")
                            {
                                status = 2;
                            }
                            else
                            {
                                LogManger.Instance.WriteLog("微信回调业务结果错误返回信息：" + builder.ToString() + ";业务结果：" + result_code);
                            }
                            LogManger.Instance.WriteLog("out_trade_no：" + out_trade_no + ";status" + status + "total_fee=" + (total_fee / 100));
                            if (status == 1 || status == 2)
                            {
                                //存储过程操作
                                var ret = _IGroupOrderService.Group_WxNotice(out_trade_no, status, (total_fee / 100), transaction_id);
                                //记日志，参数，返回值
                                LogManger.Instance.WriteLog("微信回调更改状态返回" + ret);
                            }
                            WxPayData res = new WxPayData();
                            res.SetValue("return_code", "SUCCESS");
                            res.SetValue("return_msg", "OK");
                            return base.RetMessage(res.ToXml());

                        }
                        else
                        {
                            LogManger.Instance.WriteLog("微信回调签名认证失败返回信息：" + builder.ToString() + ";接收到签名：" + return_sign + ";本地签名：" + cal_sign);
                            WxPayData res = new WxPayData();
                            res.SetValue("return_code", "FAIL");
                            res.SetValue("return_msg", "签名失败");
                            return base.RetMessage(res.ToXml());
                        }
                    }
                    else
                    {
                        //SystemLog.WriteFile("微信回调获取商户信息失败返回信息：" + builder.ToString());
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "商户不存在");
                        return base.RetMessage(res.ToXml());
                    }
                }
                else
                {
                    //SystemLog.WriteFile("微信回调返回失败返回信息：" + builder.ToString());
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "参数格式校验错误");
                    return base.RetMessage(res.ToXml());
                }
            }
            catch (Exception ex)
            {
                LogManger.Instance.WriteLog("微信回调异常，返回内容：" + builder.ToString() + ";异常信息：" + ex.Message + ";异常堆栈：" + ex.StackTrace);
                WxPayData res = new WxPayData();
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", "回调数据异常");
                return base.RetMessage(res.ToXml());
            }
            finally
            {

            }
        }

        /// <summary>
        /// 订单列表中，从Redis获取小程序拉起支付的数据
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="orderno"></param>
        /// <returns></returns>
        [HttpGet]
        public ApiResultModel<object> GetPayData(string userid, string orderno)
        {
            if (string.IsNullOrEmpty(userid) || string.IsNullOrEmpty(orderno))
                return Error("非法参数");
            string _userid = base.ValidataParms(userid);
            if (_userid == null)
                return Error("用户异常");
            //从redis获取拉起支付所需的缓存数据
            var res = RedisManager.Get<Api_GroupCreateOrderResultModel>(orderno + _userid);
            if (res == null)
                return Error("获取支付数据失败");
            return Success(res);
        }
    }
}